/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/*!		\file		ExplMdl.h
		\date		june 2010
		\author		TNick

		\brief		Definition of explorer related classes


	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	Please read ReadMe.txt and Licence.txt in root folder
	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


*/
/* ------------------------------------------------------------------------- */
/* ========================================================================= */
#ifndef		__EXPLMDL_INC__
#define		__EXPLMDL_INC__
#ifdef		__cplusplus
//
//
//
//
/*  INCLUDES    ------------------------------------------------------------ */

class	ExplNode;
class	ExplModel;
class	CC_Draw;

#include <QAbstractItemModel>
#include <QModelIndex>
#include <QVariant>
#include <QIcon>


#include "../../generic/cc_l2d.h"


/*  INCLUDES    ============================================================ */
//
//
//
//
/*  CLASS    --------------------------------------------------------------- */

/// base class for an item in explorer
/**
*	This represents an generic item placed in tree explorer. Design must
*	allow for a chain of items like this to be used both independently and
*	in big chain.
*/
class		ExplItem	: public CC_L2D	{

	//
	//
	//
	//
	/*  DEFINITIONS    ----------------------------------------------------- */

	friend class ExplNode;
	friend class ExplModel;

	enum	FLAGS	{
		FNONE = 0x0000,		/**< no flag is set */
		FEXT_TXT = 0x0001,	/**< the text shall not be
							freed by the destructor */
		FEXT_ICN = 0x0002,	/**< the icon shall not be
							freed by the destructor */
		FNODE = 0x0004,		/**< this item is a ExplNode */
		FPMDL = 0x0008,		/**< the parent is the model */

		FMAX	/**< validation */
	};

	/*  DEFINITIONS    ===================================================== */
	//
	//
	//
	//
	/*  DATA    ------------------------------------------------------------ */

private:

	/// address of the parent
	union	{
		ExplNode *		parentItem;
		ExplModel*		parentModel;
	};

	/// text shown by this item
	QString*			pTxt;

	/// icon featured by this item
	QIcon*				pIcon;

	/// various flags
	FLAGS				flg;

	/// list of columns
	QList<QVariant>		columns;



	/*  DATA    ============================================================ */
	//
	//
	//
	//
	/*  FUNCTIONS    ------------------------------------------------------- */

public:

	/// constructor; saves the father and inserts this as last kid of father
						ExplItem		(
		ExplModel *	mdl,			/**< pointer to the
									model where we're inserting */
		ExplNode *	parent = NULL,	/**< pointer to father item */
		QString *	name = NULL,	/**< the text for the item */
		QIcon *		icon = NULL		/**< the icon for the item */
	);

	/// destructor; removes the item from the chain
	virtual				~ExplItem		(void);



	/// tell the number of childs
	virtual int			childCount		(void) const { return 0; }

	/// get a pointer to the parent
	inline ExplNode *	parent			(void) { return parentItem; }

	/// return the index of this item inside parent
	inline int			row				(void);

	/// return a pointer to nth child
	virtual ExplItem *	child			(
		int			row = 0		/**< index of the child */
		) { Q_UNUSED(row); return NULL; }

	/// tell if this item is a node or a leaf
	inline bool			isNode			(void)
		{ return ((flg & FNODE) != 0); }

	/// tell if this item shares the text or it's a local text
	inline bool			isTextShared	(void)
		{ return ((flg & FEXT_TXT) == 0); }
	/// set if this item shares the text or it's a local text
	inline void			TextShared		(bool bSh)
	{
		if (bSh)	flg = static_cast<FLAGS>(flg | FEXT_TXT);
		else flg = static_cast<FLAGS>(flg & (~FEXT_TXT));
	}


	/// tell if this item shares the icon or it's a local icon
	inline bool			isIconShared	(void)
		{ return ((flg & FEXT_ICN) == 0); }
	/// set if this item shares the icon or it's a local icon
	inline void			IconShared		(bool bSh)
	{
		if (bSh)	flg = static_cast<FLAGS>(flg | FEXT_ICN);
		else flg = static_cast<FLAGS>(flg & (~FEXT_ICN));
	}


	/// tell if the parent of this item is the model or a node
	inline bool			isModelTheFather	(void)
		{ return ((flg & FPMDL) != 0); }

	/// set if the parent of this item is the model or a node
	inline void			ModelIsParent		(bool bMdl)
	{
		if (bMdl)	flg = static_cast<FLAGS>(flg | FPMDL);
		else		flg = static_cast<FLAGS>(flg & (~FPMDL));
	}

	/// set the data associated with a column
	inline void			setData			(int i, QVariant iData)
	{
	if (i < columns.count()) columns[i] = iData;
	else
	{
		while (columns.count() < i)
		{
			columns.append(QVariant());
		}
		columns.append(iData);
	}
	}
	/// get the data associated with a column
	inline QVariant		data			(int i)
	{
		if (i < columns.count()) return columns[i];
		else	return QVariant();
	}

	/// number of columns
	inline int			columnCount		(void)
	{ return columns.count() + 1; }

	/// the icon
	inline QIcon		mainIcon		(void)
	{ return *pIcon; }

	/// the text
	inline QString		mainLabel		(void)
	{ return *pTxt; }






	/*  FUNCTIONS    ======================================================= */
	//
	//
	//
	//

};	/*	class		ExplItem	*/

/*  CLASS    =============================================================== */
//
//
//
//
/*  CLASS    --------------------------------------------------------------- */

/// base class for a node item in explorer
class		ExplNode : public ExplItem		{

	//
	//
	//
	//
	/*  DEFINITIONS    ----------------------------------------------------- */
	friend class ExplItem;


	/*  DEFINITIONS    ===================================================== */
	//
	//
	//
	//
	/*  DATA    ------------------------------------------------------------ */

protected:

	/// pointer to first kid
	CC_HDL2D			hd;

	/*  DATA    ============================================================ */
	//
	//
	//
	//
	/*  FUNCTIONS    ------------------------------------------------------- */

public:

	/// constructor; saves the father and inserts this as last kid of father
						ExplNode		(
		ExplModel *	mdl,			/**< pointer to the
									model where we're inserting */
		ExplNode *	parent = NULL,	/**< pointer to father item */
		QString *	name = NULL,	/**< the text for the item */
		QIcon *		icon = NULL		/**< the icon for the item */
	) : ExplItem(mdl, parent, name, icon)
	{ flg = static_cast<FLAGS>(flg | ExplItem::FNODE); }

	/// destructor; removes the item from the chain
	/**
	*	at the time of the destruction of hd it's destructor will be called
	*	which, in turn, will recursivelly free all it's children
	*/
	virtual				~ExplNode		(void) { };


	/// append a child as last one in the chain
	/**
	*	the function does not modify the item values; those shall
	*	be updated by the caller
	*/
	inline void			append			(ExplItem* pIt)
	{ hd.append(pIt); }


	/// tell the number of childs
	virtual int			childCount		(void) const
		{ ExplNode* pDC = (ExplNode*)this;
			return pDC->hd.count(); }

	/// return a pointer to nth child
	virtual ExplItem *	child			(
		int			row = 0		/**< index of the child */
		) { return static_cast<ExplItem*>(hd.item(row)); }


	/*  FUNCTIONS    ======================================================= */
	//
	//
	//
	//

};	/*	class		ExplNode	*/

/*  CLASS    =============================================================== */
//
//
//
//
/*  CLASS    --------------------------------------------------------------- */

/// model used by the explorer window to present a drawing
class ExplModel : public QAbstractItemModel
{

	//
	//
	//
	//
	/*  DEFINITIONS    ----------------------------------------------------- */

	friend class ExplItem;

	Q_OBJECT

	/*  DEFINITIONS    ===================================================== */
	//
	//
	//
	//
	/*  DATA    ------------------------------------------------------------ */

private:

	/// pointer to first kid
	CC_HDL2D			hd;
	/// pointer to associated drawing
	CC_Draw*			pD;

	/*  DATA    ============================================================ */
	//
	//
	//
	//
	/*  FUNCTIONS    ------------------------------------------------------- */

public:

	/// constructor;
						ExplModel		(
		QObject *	parent = NULL,	/**< pointer to father */
		CC_Draw *	pDraw = NULL	/**< associated drawing */
		) : QAbstractItemModel(parent)
		{ pD = pDraw; hd.setFirst(NULL); hd.setCount(0); }

	/// destructor;
	/**
	*	at the time of the destruction of hd it's destructor will be called
	*	which, in turn, will recursivelly free all it's children
	*/
	virtual				~ExplModel		(void) { pD = NULL; }


	/// append a child as last one in the chain
	inline void			append			(ExplItem* pIt)
		{ hd.append(pIt); }


	/// tell the number of childs
	inline int			childCount		(void)
		{ return hd.count(); }

	/// return a pointer to nth child
	inline ExplItem *	child			(
		int			row = 0		/**< index of the child */
		) { return static_cast<ExplItem*>(hd.item(row)); }


	/* >>>>>>>>>>  REQUIRED BY QAbstractItemModel  <<<<<<<<<<<<<<<<<<<< */


	QVariant			data		(const QModelIndex &index, int role) const;
	Qt::ItemFlags		flags		(const QModelIndex &index) const;
 //   QVariant			headerData	(
	//	int					section,
	//	Qt::Orientation		orientation,
	//	int role = Qt::DisplayRole
	//) const;


	QModelIndex			index		(
		int					a_row,
		int					a_column,
		const QModelIndex	&parent = QModelIndex()
	) const;

	/// address of the parent
	QModelIndex			parent		(
		const QModelIndex	&index
	) const;

	/// number of rows
	int					rowCount	(
		const QModelIndex &parent = QModelIndex()
	) const;

	/// number of columns
	int					columnCount				(
		const QModelIndex	&parent = QModelIndex()
	) const;


	/*  FUNCTIONS    ======================================================= */
	//
	//
	//
	//

};	/*	class		ExplModel	*/

/*  CLASS    =============================================================== */
//
//
//
//
#endif	//	__cplusplus
#endif	//	__CC_DRAW_INC__
/* ------------------------------------------------------------------------- */
/* ========================================================================= */




////
////
////
////{
////public:
////
////	/// a new child is appended
////    void			appendChild		(ExplItem *child);
////    int				columnCount		() const;
////    QVariant		data			(int column) const;
////	void			setData			(int column, QVariant TheData);
////
////private:
////	/// list of pointers to kids
////    QList<ExplItem*>	childItems;
////	/// data for this item
////    QList<QVariant>		itemData;
////};
////
////
////
////
////
////
////class ExplModel : public QAbstractItemModel
////{
////    Q_OBJECT
////
////public:
////    ExplModel(QObject *parent = 0);
////    ~ExplModel();
////
////
////	/// this is an internally stored root item
////	inline ExplItem *	invisibleRootItem		(void)
////			{return rootItem; }
////
////
////private:
////    void setup_modelData(const QStringList &lines, ExplItem *parent);
////
////    ExplItem *rootItem;
////};
////
